﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using InterfacesPhoneCommands;
using Microsoft.SmartDevice.Connectivity;
using RemoteApplication = Microsoft.SmartDevice.Connectivity.RemoteApplication;
using SystemInfo = InterfacesPhoneCommands.ResponseSystemInfo;

namespace Phone8
{
    public class PhoneApi : IPhoneApi
    {
        private const string RootIsoTemplate = "%FOLDERID_APPID_ISOROOT%\\{0}\\";
        private Device _currentDevive;
        private ResponseSystemInfo _systemInfo;

        public ResponseConnectableDevice Device()
        {
            if (_currentDevive == null)
            {
                return new ResponseConnectableDevice { ErrorMessage = "Phone Instance not exist", Successful = false };
            }
            var item = new ConnectableDevice
            {
                Id = _currentDevive.Id.ToString(),
                IdNative = _currentDevive.Id.ToString(),
                IsEmulator = _currentDevive.IsEmulator(),
                IsLegacyEmulator = false,
                Name = _currentDevive.Name
            };

            return new ResponseConnectableDevice { Successful = true, Value = new[] { item } };
        }

        public ResponseVoid ConnectPhone(string guidDevice)
        {
            var result = new ResponseVoid();
            try
            {
                var ds = new DatastoreManager(Thread.CurrentThread.CurrentCulture.LCID);
                Platform pla = ds.GetPlatforms().FirstOrDefault();
                if (pla != null)
                {
                    if (_currentDevive != null)
                    {
                        _currentDevive.Disconnect();
                    }
                    _currentDevive = pla.GetDevice(new ObjectId(guidDevice));
                    _currentDevive.Connect();
                    Microsoft.SmartDevice.Connectivity.SystemInfo sysinfo = _currentDevive.GetSystemInfo();
                    _systemInfo = new SystemInfo
                                      {
                                          AvailPhys = sysinfo.AvailPhys,
                                          AvailVirtual = sysinfo.AvailVirtual,
                                          InstructionSet = sysinfo.InstructionSet.ToString(),
                                          NumberOfProcessors = sysinfo.NumberOfProcessors,
                                          OsBuildNo = sysinfo.OSBuildNo,
                                          OsMajor = sysinfo.OSMajor,
                                          ProcessorArchitecture = sysinfo.ProcessorArchitecture.ToString(),
                                          TotalPhys = sysinfo.TotalPhys,
                                          TotalVirtual = sysinfo.TotalVirtual,
                                          Successful = true
                                      };
                    result.Successful = true;
                    result.ReturnValue = _currentDevive.Name;
                }
                else
                {
                    _currentDevive = null;
                    _systemInfo = null;
                    result.ErrorMessage = "Device Platform not found";
                    result.Successful = false;
                }
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid IsConnected()
        {
            var result = new ResponseVoid();
            try
            {
                result.Successful = _currentDevive != null && _currentDevive.IsConnected();
                result.ReturnValue = _currentDevive != null?_currentDevive.Name:string.Empty;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseSystemInfo SystemInfo()
        {
            return IsConnected().Successful
                       ? _systemInfo
                       : new ResponseSystemInfo
                             {
                                 ProcessorArchitecture = string.Empty,
                                 InstructionSet = string.Empty,
                                 Successful = false,
                                 ErrorMessage = "Phone Not connected"
                             };
        }

        public ResponseVoid Disconnect()
        {
            var result = new ResponseVoid();
            try
            {
                if (_currentDevive != null)
                {
                    if (_currentDevive.IsConnected())
                    {
                        _currentDevive.Disconnect();
                    }
                }
                _currentDevive = null;
                _systemInfo = null;
                result.Successful = true;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid Launch(string guidapp)
        {
            var result = new ResponseVoid();
            try
            {
                RemoteApplication remapp = _currentDevive.GetApplication(new Guid(guidapp));
                remapp.Launch();
                _currentDevive.Activate();
                result.Successful = true;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid TerminateRunningInstances(string guidapp)
        {
            var result = new ResponseVoid();
            try
            {
                RemoteApplication remapp = _currentDevive.GetApplication(new Guid(guidapp));
                remapp.TerminateRunningInstances();
                result.Successful = true;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid Uninstall(string guidapp)
        {
            var result = new ResponseVoid();
            try
            {
                RemoteApplication remapp = _currentDevive.GetApplication(new Guid(guidapp));
                remapp.Uninstall();
                result.Successful = true;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid InstallApplication(Guid guid, Guid instance, string genre, string iconpath,
                                               string xapPackege)
        {
            var result = new ResponseVoid();
            try
            {
                _currentDevive.InstallApplication(guid, instance, genre, iconpath, xapPackege);
                result.Successful = true;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid IsApplicationInstalled(Guid guid)
        {
            var result = new ResponseVoid();
            try
            {
                result.Successful = _currentDevive.IsApplicationInstalled(guid);
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid UpdateApplication(string guidapp, string genre, string iconfile, string filename)
        {
            var result = new ResponseVoid();
            try
            {
                RemoteApplication remapp = _currentDevive.GetApplication(new Guid(guidapp));
                remapp.UpdateApplication(genre, iconfile, filename);
                result.Successful = true;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseArrayString ApplicationsInstalled()
        {
            var result = new ResponseArrayString();
            try
            {
                result.Value =
                    _currentDevive.GetInstalledApplications().Select(app => app.ProductID.ToString()).ToArray();
                result.Successful = true;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseRemoteFile GetIsoFiles(string guidapp, string pathRoot)
        {
            var result = new ResponseRemoteFile();
            try
            {
                if (string.IsNullOrEmpty(pathRoot))
                {
                    pathRoot = "\\";
                }
                string template = GetIsolatedStoreRootPath(guidapp);
                RemoteApplication remapp = _currentDevive.GetApplication(new Guid(guidapp));
                RemoteIsolatedStorageFile iso = remapp.GetIsolatedStore();
                List<RemoteFileInfo> files = iso.GetDirectoryListing(pathRoot);
                var resultf = new List<RemoteFile>();
                foreach (RemoteFileInfo remoteFileInfo in files)
                {
                    if (remoteFileInfo.IsDirectory())
                    {
                        var item = new RemoteFile
                                       {
                                           FullName = remoteFileInfo.Name,
                                           Name = remoteFileInfo.Name.Replace(template, "")
                                                                .Replace(pathRoot, "")
                                                                .Replace("\\", ""),
                                           IsRoot = (pathRoot == "\\"),
                                           IsDiretory = true
                                       };
                        string folder = remoteFileInfo.Name.Replace(template, "");
                        switch (folder)
                        {
                            case "\\IsolatedStore\\Shared":
                            case "\\IsolatedStore\\Shared\\Transfers":
                            case "\\IsolatedStore\\Shared\\ShellContent":
                            case "\\IsolatedStore\\Shared\\Media":
                            case "\\\\Shared":
                            case "\\\\Shared\\Transfers":
                            case "\\\\Shared\\ShellContent":
                            case "\\\\Shared\\Media":
                                item.IsSystem = true;
                                break;
                        }
                        resultf.Add(item);
                    }
                    else
                    {
                        var item = new RemoteFile
                                       {
                                           FullName = remoteFileInfo.Name,
                                           Name = remoteFileInfo.Name.Replace(template, "")
                                                                .Replace(pathRoot, "")
                                                                .Replace("\\", ""),
                                           IsRoot = (pathRoot == "\\"),
                                           IsDiretory = false,
                                           Length = remoteFileInfo.Length
                                       };
                        resultf.Add(item);
                    }
                }
                result.Value = resultf.ToArray();
                result.Successful = true;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid CopySendFile(string guidapp, RemoteFile isofileinfo, string newfile, bool overwrite)
        {
            var result = new ResponseVoid();
            try
            {
                string template = GetIsolatedStoreRootPath(guidapp);
                RemoteApplication remapp = _currentDevive.GetApplication(new Guid(guidapp));
                RemoteIsolatedStorageFile iso = remapp.GetIsolatedStore();
                string pathfolder = string.Empty;
                if (!isofileinfo.IsRoot)
                {
                    pathfolder = isofileinfo.FullName.Replace(template, "");
                }
                var fi = new FileInfo(newfile);
                pathfolder += "\\" + fi.Name;
                bool filereadonly = fi.IsReadOnly;
                //change attribute (prevent error when delete)
                fi.IsReadOnly = false;
                iso.SendFile(newfile, pathfolder, overwrite);
                //change attribute (restore original attribute)
                fi.IsReadOnly = filereadonly;
                result.Successful = true;
                result.ReturnValue = pathfolder;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid CopyReceiveFile(string guidapp, RemoteFile isofileinfo, string desktopTarget)
        {
            var result = new ResponseVoid();
            try
            {
                string template = GetIsolatedStoreRootPath(guidapp);
                RemoteApplication remapp = _currentDevive.GetApplication(new Guid(guidapp));
                RemoteIsolatedStorageFile iso = remapp.GetIsolatedStore();
                string filepath = isofileinfo.FullName.Replace(template, "");
                var deskDirinfo = new DirectoryInfo(desktopTarget);
                if (!isofileinfo.IsRoot)
                {
                    deskDirinfo = CreateDesktopSubdirectory(guidapp, desktopTarget, isofileinfo, isofileinfo.Name);
                }

                string targetfile = Path.Combine(deskDirinfo.FullName, isofileinfo.Name);
                iso.ReceiveFile(filepath, targetfile, true);
                result.Successful = true;
                result.ReturnValue = deskDirinfo.FullName;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid RenameFile(string guidapp, RemoteFile isofileinfo, string newfile)
        {
            var result = new ResponseVoid();
            try
            {
                string template = GetIsolatedStoreRootPath(guidapp);
                RemoteApplication remapp = _currentDevive.GetApplication(new Guid(guidapp));
                RemoteIsolatedStorageFile iso = remapp.GetIsolatedStore();
                string pathfolder = string.Empty;
                if (!isofileinfo.IsRoot)
                {
                    pathfolder = isofileinfo.FullName.Replace(template, "");
                }
                string filetemp = Path.GetTempPath() + "\\" + newfile;
                string newpathfile = pathfolder.Replace(isofileinfo.Name, newfile);
                iso.ReceiveFile(pathfolder, filetemp, true);
                iso.SendFile(filetemp, newpathfile, true);
                iso.DeleteFile(pathfolder);
                if (File.Exists(filetemp))
                {
                    File.Delete(filetemp);
                }
                result.Successful = true;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid DeleteFile(string guidapp, RemoteFile isofileinfo)
        {
            var result = new ResponseVoid();
            try
            {
                string template = GetIsolatedStoreRootPath(guidapp);
                RemoteApplication remapp = _currentDevive.GetApplication(new Guid(guidapp));
                RemoteIsolatedStorageFile iso = remapp.GetIsolatedStore();
                string pathfolder = isofileinfo.FullName.Replace(template, "");
                iso.DeleteFile(pathfolder);
                result.Successful = true;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid DeleteDir(string guidapp, RemoteFile isofileinfo)
        {
            var result = new ResponseVoid();
            try
            {
                RemoteApplication remapp = _currentDevive.GetApplication(new Guid(guidapp));
                RemoteIsolatedStorageFile iso = remapp.GetIsolatedStore();
                string template = GetIsolatedStoreRootPath(guidapp);
                string pathfolder = string.Empty;
                if (isofileinfo != null)
                {
                    pathfolder = isofileinfo.FullName.Replace(template, "");
                }
                iso.DeleteDirectory(pathfolder);
                result.Successful = true;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid DirectoryExists(string guidapp, string folder)
        {
            var result = new ResponseVoid();
            try
            {
                RemoteApplication remapp = _currentDevive.GetApplication(new Guid(guidapp));
                RemoteIsolatedStorageFile iso = remapp.GetIsolatedStore();
                string pathfolder = "\\" + folder;
                result.Successful = iso.DirectoryExists(pathfolder);
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid FileExists(string guidapp, string file)
        {
            var result = new ResponseVoid();
            try
            {
                RemoteApplication remapp = _currentDevive.GetApplication(new Guid(guidapp));
                RemoteIsolatedStorageFile iso = remapp.GetIsolatedStore();
                string pathfolder = "\\" + file;
                result.Successful = iso.FileExists(pathfolder);
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        public ResponseVoid CreateDir(string guidapp, RemoteFile isofileinfo, string newfolder)
        {
            var result = new ResponseVoid();
            try
            {
                string template = GetIsolatedStoreRootPath(guidapp);
                RemoteApplication remapp = _currentDevive.GetApplication(new Guid(guidapp));
                RemoteIsolatedStorageFile iso = remapp.GetIsolatedStore();
                string pathfolder = string.Empty;
                if (!isofileinfo.IsRoot)
                {
                    pathfolder = isofileinfo.FullName.Replace(template + "\\", "");
                }
                pathfolder += "\\" + newfolder;
                iso.CreateDirectory(pathfolder);
                result.Successful = true;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                if (ex.InnerException != null)
                {
                    err += " InnerException : " + ex.InnerException.Message;
                }
                result.ErrorMessage = err;
                result.Successful = false;
            }
            return result;
        }

        private static string GetIsolatedStoreRootPath(string guidapp)
        {
            return string.Format(RootIsoTemplate, "{" + guidapp + "}");
        }

        private static DirectoryInfo CreateDesktopSubdirectory(string guidapp, string rootTarget, RemoteFile isofileinfo,
                                                               string filename)
        {
            string template = GetIsolatedStoreRootPath(guidapp);
            string folderpath = isofileinfo.FullName.Replace(template, "");
            if (!string.IsNullOrEmpty(filename))
            {
                folderpath = folderpath.Replace(filename, "");
            }

            string[] folders = folderpath.Split(new[] {'\\'}, StringSplitOptions.RemoveEmptyEntries);

            DirectoryInfo[] destotoptarget = {new DirectoryInfo(rootTarget)};
            foreach (
                string item in folders.Where(item => !Directory.Exists(Path.Combine(destotoptarget[0].FullName, item))))
            {
                destotoptarget[0] = destotoptarget[0].CreateSubdirectory(item);
            }

            return destotoptarget[0];
        }
    }
}